#include "SPI_SoftSimu.h"


#define SCLK_SET_H(hSSPI)  HAL_GPIO_WritePin(hSSPI->CLK_Port,  hSSPI->CLK_Pin,  GPIO_PIN_SET)
#define SCLK_SET_L(hSSPI)  HAL_GPIO_WritePin(hSSPI->CLK_Port,  hSSPI->CLK_Pin,  GPIO_PIN_RESET)
#define CS_SET_H(hSSPI)    HAL_GPIO_WritePin(hSSPI->CS_Port,   hSSPI->CS_Pin,   GPIO_PIN_SET)
#define CS_SET_L(hSSPI)    HAL_GPIO_WritePin(hSSPI->CS_Port,   hSSPI->CS_Pin,   GPIO_PIN_RESET)
#define MOSI_SET_H(hSSPI)  HAL_GPIO_WritePin(hSSPI->MOSI_Port, hSSPI->MOSI_Pin, GPIO_PIN_SET)
#define MOSI_SET_L(hSSPI)  HAL_GPIO_WritePin(hSSPI->MOSI_Port, hSSPI->MOSI_Pin, GPIO_PIN_RESET)
#define MISO_READ(hSSPI)   HAL_GPIO_ReadPin (hSSPI->MISO_Port, hSSPI->MISO_Pin)


#define SPI_SET_BIT_INIT(data)  do{if((data&0x80)==0x80){MOSI_SET_H(hSSPI);}else{MOSI_SET_L(hSSPI);}}while(0)
#define SPI_SEND_BIT(data)      do{if((data&0x80)==0x80){MOSI_SET_H(hSSPI);data<<=1;}else{MOSI_SET_L(hSSPI);data<<=1;}}while(0)
#define SPI_READ_BIT(output)    do{if(MISO_READ(hSSPI)){output|=0x01;output<<=1;}}while(0)
#define SPIDelay                do{__NOP();__NOP();}while(0)


uint8_t SPI_RW_BYTE(const Soft_SPI* hSSPI, uint8_t data)
{
  uint32_t i;
  uint8_t output=0;
  
  switch (hSSPI->SPI_mode)
  {
  case 0:
    SCLK_SET_H(hSSPI); 
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<8;i++)
    {   
      SCLK_SET_L(hSSPI);  
      SPI_SEND_BIT(data);  //下降沿发送
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      SCLK_SET_H(hSSPI); 
      SPI_READ_BIT(output);//上升沿采样,注意，必须先准备好数据，再才升上升沿，否则会出现第一个包不正确的情况。
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间        
    }
    SCLK_SET_L(hSSPI); 
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 1:
    SCLK_SET_L(hSSPI);  
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<8;i++)
    {   
      SCLK_SET_H(hSSPI);
      SPI_SEND_BIT(data);  //上升沿发送
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      SCLK_SET_L(hSSPI); 
      SPI_READ_BIT(output);//下降沿采样
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
    }
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 2:
    SCLK_SET_L(hSSPI); 
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<8;i++)
    {   
      SCLK_SET_H(hSSPI);             
      SPI_SEND_BIT(data);  //上升沿发送
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      SCLK_SET_L(hSSPI);     
      SPI_READ_BIT(output);//下降沿采样
      SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
    }
    SCLK_SET_H(hSSPI);
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 3:
    SCLK_SET_H(hSSPI); 
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<8;i++)
    {   
      SCLK_SET_L(hSSPI);              
      SPI_SEND_BIT(data);   //下降沿发送
      SPIDelay;             //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      SCLK_SET_H(hSSPI);             
      SPI_READ_BIT(output); //上升沿采样
      SPIDelay;             //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
    }
    SCLK_SET_H(hSSPI); 
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  default:
    break;
  }
  return output;
}

void SPI_WRITE_BUF(const Soft_SPI* hSSPI, uint8_t *pData, int len)
{
  uint32_t i, j;
  uint8_t  data=0;

  switch (hSSPI->SPI_mode)
  {
  case 0:
    SCLK_SET_H(hSSPI); 
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<len;i++)
    {
      data = pData[i];
      for(j=0;j<8;j++)
      {
        SCLK_SET_L(hSSPI);              
        SPI_SEND_BIT(data);   //下降沿发送
        SPIDelay;             //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
        SCLK_SET_H(hSSPI);             
        SPIDelay;             //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      }
    }
    SCLK_SET_L(hSSPI); 
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 1:
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<len;i++)
    {
      data = pData[i];
      for(j=0;j<8;j++)
      {
        SCLK_SET_H(hSSPI);
        SPI_SEND_BIT(data);  //上升沿发送
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
        SCLK_SET_L(hSSPI);
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      }
    }
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 2:
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<len;i++)
    {
      data = pData[i];
      for(j=0;j<8;j++)
      {
        SCLK_SET_H(hSSPI);
        SPI_SEND_BIT(data);  //上升沿发送
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
        SCLK_SET_L(hSSPI);
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      }
    }
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  case 3:
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_L(hSSPI);
    SPIDelay;
    for(i=0;i<len;i++)
    {
      data = pData[i];
      for(j=0;j<8;j++)
      {
        SCLK_SET_H(hSSPI);
        SPI_SEND_BIT(data);  //上升沿发送
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
        SCLK_SET_L(hSSPI);
        SPIDelay;            //每次时钟变化之前，进行delay，确保数据稳定，对方有足够的采样时间
      }
    }
    SCLK_SET_L(hSSPI);
    SPIDelay;
    CS_SET_H(hSSPI);
    SPIDelay;
    break;
  default:
    break;
  }
}
